package com.mf.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.Enum.EnumNextProcess;
import com.mf.Enum.EnumWorkType;
import com.mf.constant.ConstantBasic;
import com.mf.entity.dto.DtoIncomingDetail;
import com.mf.entity.dto.DtoRive;
import com.mf.entity.dto.DtoRiveDetail;
import com.mf.entity.dto.DtoSortOut;
import com.mf.entity.req.ReqRelevancyById;
import com.mf.entity.req.publicReq.ReqPublicIds;
import com.mf.entity.req.search.SearchReqIncomingDetail;
import com.mf.entity.req.search.SearchReqRiveDetail;
import com.mf.entity.req.search.SearchReqSortOut;
import com.mf.exception.GraceException;
import com.mf.mapper.MapperRiveDetail;
import com.mf.service.ServiceIncomingDetail;
import com.mf.service.ServiceRive;
import com.mf.service.ServiceRiveDetail;
import com.mf.service.ServiceSortOut;
import com.mf.utils.UtilEnumNextProcess;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class ImplServiceRiveDetail extends ServiceImpl<MapperRiveDetail, DtoRiveDetail> implements ServiceRiveDetail {
    @Resource
    private ServiceSortOut serviceSortOut;

    @Resource
    private ServiceRive serviceRive;

    @Resource
    private ServiceIncomingDetail serviceIncomingDetail;

    /**
     * 参数查询条件
     */
    @Override
    public LambdaQueryWrapper<DtoRiveDetail> fillParams(SearchReqRiveDetail params) {
        LambdaQueryWrapper<DtoRiveDetail> wrapper = loadQw();
        if (StringUtils.isNotEmpty(params.getKey())) {
            wrapper.and(w -> {
                w.like(DtoRiveDetail::getMaterailName, params.getKey())
                        .or()
                        .like(DtoRiveDetail::getMaterailWeight, params.getKey());
            });
        }

        wrapper.eq(DtoRiveDetail::getRiveId, params.getRiveId())
                .eq(ObjectUtils.isNotEmpty(params.getSourceId()), DtoRiveDetail::getSourceId, params.getSourceId())
                .eq(ObjectUtils.isNotEmpty(params.getMaterialId()), DtoRiveDetail::getMaterialId,
                        params.getMaterialId())
                .eq(ObjectUtils.isNotEmpty(params.getNextProcess()), DtoRiveDetail::getNextProcess,
                        params.getNextProcess());

        return wrapper;
    }

    /**
     * 删除
     */
    @Override
    public void removeDetailById(Integer riveId, Integer id) {
        LambdaQueryWrapper<DtoRiveDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DtoRiveDetail::getRiveId, riveId)
                .eq(DtoRiveDetail::getId, id);
        // 查询是否有对应明细
        DtoRiveDetail riveDetail = getOne(wrapper);
        if (ObjectUtils.isEmpty(riveDetail)) {
            GraceException.display("撕碎明细【" + riveId + "】不存在");
        }

        // 当前关联的是分拣工单
        if (EnumWorkType.SORT.getCode().equals(riveDetail.getWorkSource())) {
            serviceSortOut.updateRelevancyBySourceId(List.of(riveDetail.getSourceId()), ConstantBasic.NO_RELEVANCY);
        } else if (EnumWorkType.IN.getCode().equals(riveDetail.getWorkSource())) {

            List<ReqRelevancyById> relevancyByIds = new ArrayList<>();
            relevancyByIds.add(new ReqRelevancyById(id, ConstantBasic.NO_RELEVANCY));
            serviceIncomingDetail.setRelevancy(relevancyByIds, riveDetail.getSourceId(), riveDetail.getWorkSource());
        }

        this.removeById(id);
    }

    /**
     * 保存
     */
    @Override
    @Transactional
    public void saveDetail(List<Integer> detailIds, Integer riveId, Integer sourceId, Integer workSource) {

        DtoRive rive = serviceRive.getById(riveId);
        if (rive == null) {
            GraceException.display("分拣工单【" + riveId + "】不存在");
        }
        List<DtoRiveDetail> dtoRiveDetails = new ArrayList<>();


        // 查询分拣产出 下工序撕碎没有关联以及对应的分拣工单
        if (EnumWorkType.SORT.getCode().equals(workSource)) {
            SearchReqSortOut params = SearchReqSortOut.builder()
                    .sortId(sourceId)
                    .nextProcess(EnumNextProcess.RIVE.getCode())
                    .relevancyWork(ConstantBasic.NO_RELEVANCY)
                    .build();
            List<DtoSortOut> sortOutList = serviceSortOut.findListByParams(params);


            // 装换为map集合
            Map<Integer, DtoSortOut> sortOutMap = sortOutList.stream().collect(Collectors.toMap(DtoSortOut::getId,
                    v -> v));


            for (Integer id : detailIds) {
                if (!sortOutMap.containsKey(id)) {
                    GraceException.display("分拣明细【" + id + "】不存在");
                }
                DtoSortOut dtoSortOut = sortOutMap.get(id);
                DtoRiveDetail riveDetail = DtoRiveDetail.builder()
                        .riveId(riveId)
                        .sourceId(id)
                        .workSource(workSource)
                        .materailName(dtoSortOut.getMaterailName())
                        .materialId(dtoSortOut.getMaterialId())
                        .materailWeight(Math.ceil(dtoSortOut.getWeight() * rive.getOutRatio() / 100))
                        .nextProcess(EnumNextProcess.SMASH.getCode())
                        .build();
                dtoRiveDetails.add(riveDetail);
            }
            serviceSortOut.updateRelevancyBySourceId(detailIds, riveId);
        } else if (EnumWorkType.IN.getCode().equals(workSource)) {
            // 来料单详情

            Map<Integer, DtoIncomingDetail> detailMap = serviceIncomingDetail.getDtoIncomingDetailMap(sourceId,
                    workSource);
            List<ReqRelevancyById> relevancyByIds = new ArrayList<>();

            for (Integer id : detailIds) {
                serviceIncomingDetail.setRelevancyList(sourceId, id, detailMap, relevancyByIds);
                DtoIncomingDetail incomingDetail = detailMap.get(id);
                DtoRiveDetail riveDetail = DtoRiveDetail.builder()
                        .riveId(riveId)
                        .sourceId(id)
                        .workSource(workSource)
                        .materailName(incomingDetail.getMaterialInfo())
                        .materialId(incomingDetail.getMaterialId())
                        .materailWeight(incomingDetail.getGrossWeight())
                        .nextProcess(EnumNextProcess.SMASH.getCode())
                        .build();
                dtoRiveDetails.add(riveDetail);
            }

            serviceIncomingDetail.setRelevancy(relevancyByIds, sourceId, EnumWorkType.RIVE.getCode());
        } else {
            GraceException.display("未知的工单类型");
        }
        this.saveBatch(dtoRiveDetails);
    }

    /**
     * 根据源id，类型查询对应map集合
     */
    @Override
    public Map<Integer, DtoRiveDetail> getDtoRiveDetailMap(Integer riveId, Integer nextProcess) {
        final SearchReqRiveDetail params = SearchReqRiveDetail.builder()
                .riveId(riveId)
                .relevancyId(ConstantBasic.NO_RELEVANCY)
                .nextProcess(nextProcess)
                .build();

        final List<DtoRiveDetail> listByParams = this.findListByParams(params);
        return listByParams.stream().collect(Collectors.toMap(DtoRiveDetail::getId, v -> v));
    }
    /**
     * 根据id,关联id，类型设置关联信息
     */
    @Override
    @Transactional
    public void setRelevancy(List<ReqRelevancyById> relevancyByIds, Integer sourceId, Integer relevancyType) {
        List<DtoRiveDetail> details = new ArrayList<>();
        for (ReqRelevancyById relevancy : relevancyByIds) {
            details.add(DtoRiveDetail.builder()
                    .id(relevancy.getId())
                    .relevancyId(relevancy.getRelevancyId())
                    .relevancyType(relevancyType)
                    .build());
        }
        // 更新对应的关联信息
        updateBatchById(details);

        // 查询当前明细是否全部关联完成
        final LambdaQueryWrapper<DtoRiveDetail> wrapper = loadQw();
        wrapper.eq(DtoRiveDetail::getRiveId, sourceId);
        final List<DtoRiveDetail> incomingDetails = list();
        for (DtoRiveDetail incomingDetail : incomingDetails) {
            if (ConstantBasic.NO_RELEVANCY.equals(incomingDetail.getRelevancyId())) {
                // 没有更新完成,同步关联状态
                serviceRive.updateRelevancyStatus(sourceId, ConstantBasic.NO_RELEVANCY);
                return;
            }
        }
        serviceRive.updateRelevancyStatus(sourceId, ConstantBasic.RELEVANCY_STATUS_YES);
    }
}